home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------------*/
- /* The Opus Computer-Based Conversation System */
- /* (c) Copyright 1986, Wynn Wagner III, All Rights Reserved */
- /* */
- /* The original Sealink protocol is copyrighted by SEA, inc. */
- /* */
- /* This module was written by W.Wagner III */
- /* with modifications done by Bob Hartman and Rick Huebner */
- /* */
- /* */
- /* */
- /* GENERAL PURPOSE FILE RECEPTION (Xmodem/YModem/Sealink) */
- /* */
- /* */
- /* This module is similar to a routine used by Opus-Cbcs (1.00). It is */
- /* provided for your information only. You will find routines that need */
- /* to be coded and identifiers to be resolved. */
- /* */
- /* There is absolutely no guarantee that anything here will work. If you */
- /* break this routine, you own both pieces. */
- /* */
- /* USAGE: You may use this material in any program with no obligation */
- /* as long as there is no charge for your program. For more */
- /* information about commercial use, contact the "OPUSinfo HERE" */
- /* BBS (124/111). */
- /* */
- /* */
- /*--------------------------------------------------------------------------*/
- #include <sys/types.h>
- #include <sys/utime.h>
- #include <ctype.h>
- #include <stdio.h>
- #include "xfer.h"
- #include "com.h"
-
-
-
-
-
- static void pascal SendACK(void);
- static void pascal SendNAK(void);
- static void pascal getblock(void);
-
-
- /*--------------------------------------------------------------------------*/
- /* EXTERNALS */
- /*--------------------------------------------------------------------------*/
- extern char *UNLINK_msg;
- extern byte *local_CEOL;
- extern int remote_net, remote_node;
- extern int overwrite;
- extern int un_attended;
- extern int fullscreen;
- extern long timezone;
- extern int no_overdrive;
-
- char *ultoa();
-
-
- /*--------------------------------------------------------------------------*/
- /* LOCALS */
- /*--------------------------------------------------------------------------*/
- static unsigned int block_number;
- static unsigned int base_block;
- static char *stat_msg;
- static int sliding;
- static int block_size;
- static int do_chksum;
- static int errs;
- static int fsize1;
- static int fsize2;
- static char *buffer;
- char *malloc();
- static FILE *infile;
- static char *_fpath;
- static struct zero_block *header;
- static char final_name[80];
- static int first_block; /* 1 = first block/Matrix bundle */
-
- static char *receiving = "Receiving ";
- static int may_be_seadog;
- static int netmail;
- static int recv_ackless;
- static int did_nak;
- static long filesecs;
-
- #define two_s "%s%s"
-
-
-
- /*--------------------------------------------------------------------------*/
- /* SEND ACK */
- /*--------------------------------------------------------------------------*/
- static void pascal SendACK()
- begin
-
- if ((!recv_ackless) || (block_number == 0))
- {
- SENDBYTE( ACK );
- if (sliding)
- begin
- SENDBYTE( block_number );
- SENDBYTE( ~block_number );
- end
- }
-
- if (block_number <= fsize1)
- begin
-
- /* Non-nonsense status line. Don't waste time will frills... */
- gotoxy(locate_x,locate_y);
- cputs( ultoa(((unsigned long )(block_number)),e_input,10) );
-
- end
-
- errs = 0;
-
- end /* SendACK */
-
-
-
- /*--------------------------------------------------------------------------*/
- /* SEND NAK */
- /*--------------------------------------------------------------------------*/
- static void pascal SendNAK()
- begin
- int i;
-
- errs++;
- if (errs>6)
- begin
- stat_msg = FUBAR_msg;
- return;
- end
-
- if (++did_nak > 8)
- {
- recv_ackless = 0;
- }
-
-
- CLEAR_INBOUND();
-
-
- /*--------------------------------------------------------------------*/
- /* Let the connection cool its heels. */
- /*--------------------------------------------------------------------*/
- if (!recv_ackless)
- {
- if ((base_block!=block_number) or (errs>1))
- do
- begin
- i = TIMED_READ(1);
- if (!CARRIER) return;
- end
- while(i>=0);
- }
-
-
-
- if (block_number>base_block) SENDBYTE(NAK);
- else
- begin
- if ((errs<5) and (!do_chksum)) SENDBYTE('C');
- else
- begin
- do_chksum = 1;
- SENDBYTE(NAK);
- end
- end
-
- if (sliding)
- begin
- SENDBYTE( block_number );
- SENDBYTE( ~block_number );
- end
-
- if (block_number <= fsize1)
- begin
-
- /* No time for anything but the bare essentials... */
- gotoxy(locate_x,locate_y);
- cputs( ultoa(((unsigned long )(block_number)),e_input,10) );
-
- end
-
- end /* SendNAK */
-
-
-
- /*--------------------------------------------------------------------------*/
- /* GET BLOCK */
- /*--------------------------------------------------------------------------*/
- static void pascal getblock()
- begin
- register int i;
- register char *sptr;
-
- unsigned int crc;
- int loop;
- int in_char;
- int is_resend;
- int blockerr;
- unsigned char chksum;
-
- blockerr = loop = is_resend = 0;
- chksum = '\0';
-
-
- /*--------------------------------------------------------------------*/
- /* HEADER: Block number */
- /*--------------------------------------------------------------------*/
- in_char = TIMED_READ(5);
- if ( in_char != (block_number & 0xff) )
- begin
- if (in_char < block_number ) is_resend = 1;
- else if ((block_number) or (in_char != 1))
- begin
- blockerr++;
- stat_msg = SYNC_msg;
- end
- else block_number = 1;
- end
-
- /*--------------------------------------------------------------------*/
- /* HEADER: Complement of the block number */
- /*--------------------------------------------------------------------*/
- i = TIMED_READ(5);
- if ( (i&0xff) != ((~in_char)&0xff) )
- begin
- blockerr++;
- stat_msg = CMPL_msg;
- end
-
- /*--------------------------------------------------------------------*/
- /* DATA */
- /*--------------------------------------------------------------------*/
- for (sptr=buffer, i=0; i<block_size; i++, sptr++ )
- begin
- if (!CARRIER) return;
-
- in_char = TIMED_READ(5);
- if (in_char<0)
- begin
- SendNAK();
- stat_msg = TIME_msg;
- return;
- end
- sptr[0] = (char )in_char;
- end
-
- /*--------------------------------------------------------------------*/
- /* CHECK */
- /*--------------------------------------------------------------------*/
- if (do_chksum)
- begin
-
- for(sptr=buffer,i=0; i<block_size; i++,sptr++ )
- chksum += sptr[0];
-
- if (TIMED_READ(5)!=chksum)
- begin
- stat_msg = CHK_msg;
- blockerr++;
- end
- end
- else
- begin
- unsigned int lsb, msb;
-
- for(sptr=buffer,i=crc=0; i<block_size; i++,sptr++)
- crc = xcrc(crc,(byte )sptr[0]);
-
-
- msb = TIMED_READ(3);
- lsb = TIMED_READ(3);
- if ((lsb<0)||(msb<0))
- begin
- stat_msg = SHRT_msg;
- if (!block_number) sliding = 0;
- blockerr++;
- end
- else if ( ((msb<<8)|lsb) != crc )
- begin
- stat_msg = CRC_msg;
- blockerr++;
- end
- end
-
- if (blockerr) SendNAK();
- else
- begin
- SendACK();
- if (is_resend) return;
-
- if (block_number)
- begin
- if (block_number < fsize1)
- fwrite( buffer, block_size, 1, infile );
- else if (block_number == fsize1)
- fwrite ( buffer, fsize2, 1, infile);
-
- if (first_block)
- begin
- struct _pkthdr *bundle;
-
- bundle = (struct _pkthdr *)buffer;
- remote_net = bundle->orig_net;
- remote_node = bundle->orig_node;
- first_block = 0;
- end
- end
- else
- begin
- if (!first_block)
- begin
- sptr = &(header->name[0]);
- if (netmail)
- invent_pkt_name(sptr);
-
- for(i=0; ((sptr[i])&&(i<17)); i++)
- if (sptr[i]<=' ') sptr[i]='\0';
-
- if (sptr[0])
- begin
- sprintf( final_name, two_s, _fpath, sptr );
- sptr = final_name;
- fancy_str( sptr );
-
- i = strlen(final_name)-1;
-
- if (un_attended && fullscreen)
- {
- clear_filetransfer();
- gotoxy (0,13);
- }
- else if (locate_y>1)
- {
- gotoxy (0, locate_y - 1);
- }
- cputs( sptr );
- end
- else status_line("!Grunged hdr");
- end
- else message(NULL);
-
- if (header->size)
- begin
- fsize1 = (int) (header->size/128L);
- if (fsize2 = (header->size % 128)) ++fsize1;
- else fsize2 = 128;
- cprintf("%s %d blks", (netmail)?" ":"", fsize1);
- end
-
- if (header->time)
- begin
- filesecs = header->time;
- end
- else
- begin
- filesecs = -1;
- end
-
- if (header->moi[0]) cprintf(" from %s", header->moi );
-
- if (header->noacks && !no_overdrive)
- {
- recv_ackless = 1;
- }
-
- if (!netmail)
- {
- if (un_attended && fullscreen)
- gotoxy (0, 13);
- set_xy(receiving);
- }
-
- end
- block_number++;
- end
-
- end /* getblock */
-
-
-
-
-
-
- /*--------------------------------------------------------------------------*/
- /* GENERAL PURPOSE FILE RECEIPTION ROUTINE */
- /*--------------------------------------------------------------------------*/
- char *receive_file( fpath, fname, protocol )
- char *fpath, *fname, protocol;
- begin
- char tmpname[80];
- int in_char;
- int block_timer;
- struct utimbuf times;
- long t1, timerset();
-
- did_nak = 0;
- filesecs = -1;
- brk_disable();
- XON_DISABLE();
-
- if (protocol == 'F')
- {
- may_be_seadog = 1;
- netmail = 0;
- protocol = 'S';
- first_block = 0;
- }
- else if (protocol == 'B')
- {
- protocol = 'S';
- may_be_seadog = 1;
- netmail = 1;
- first_block = 1;
- }
- else
- {
- may_be_seadog = 0;
- netmail = 0;
- first_block = 0;
- }
-
- CLEAR_IOERR();
- fsize1 = 32767;
- if (fname)
- for(in_char=0;fname[in_char];in_char++)
- if ( (fname[in_char]=='*') || (fname[in_char]=='?') ) fname[0]='\0';
-
- _fpath = fpath;
- sliding = 1;
- base_block =
- do_chksum =
- errs = 0;
- block_size = 128;
-
- locate_y = wherey();
- locate_x = 3 + wherex();
-
- switch(protocol)
- begin
- case 'X' : base_block=1; sliding=0; break;
- case 'Y' : base_block=1; sliding=0; block_size=1024; break;
- case 'S' : break;
- case 'T' : break;
- case 'M' : base_block=1; sliding=0; break;
- default : cprintf("Protocol??\r\n"); return NULL;
- end
-
- block_number = base_block;
-
- sprintf( tmpname, "%s_TMP_.$$$", fpath );
- sprintf( final_name, two_s, _fpath,(fname&&fname[0])?fname:"UNKNOWN.$$$");
-
- infile = fopen( tmpname, write_binary );
- if (got_error(CREATE_msg,tmpname)) return(NULL);
-
- buffer = malloc(1032);
- header = (struct zero_block *) buffer;
- if (!buffer)
- begin
- status_line("!MEM:ulbuf");
- return(NULL);
- end
-
- if (un_attended && fullscreen)
- {
- gotoxy (0,13);
- }
- set_xy(receiving);
- stat_msg = NULL;
- throughput(0,0L);
-
- /* If we did the SEAdog kludge, then don't send another NAK */
- if (!may_be_seadog)
- SendNAK();
-
- t1 = timerset(300);
- do
- begin
-
- /* Pretty loose timer for things like satellite delays, etc. */
- /* block_timer = timerset(10);
- */
-
- loop_top:
- if (((KEYPRESS()) and (READKB()==27)))
- begin
- stat_msg = KBD_msg;
- goto fubar;
- end
-
- in_char = TIMED_READ(4);
-
- switch( in_char )
- begin
- case SOH : /*--------------------------------------------*/
- /* SOH: 128 byte block header */
- /*--------------------------------------------*/
- block_size=128;
- getblock();
- t1 = timerset(300);
- break;
-
- case STX : /*--------------------------------------------*/
- /* STX: YModem 1k block header */
- /*--------------------------------------------*/
- block_size=1024;
- getblock();
- t1 = timerset(300);
- break;
-
- case SYN : /*--------------------------------------------*/
- /* SYN: TeLink Zero block header */
- /*--------------------------------------------*/
- do_chksum = 1;
- getblock();
- do_chksum = 0;
- t1 = timerset(300);
- break;
-
- case CAN : /*--------------------------------------------*/
- /* CAN */
- /*--------------------------------------------*/
- if (TIMED_READ(2)==CAN)
- begin
- stat_msg = CAN_msg;
- goto fubar;
- end
- t1 = timerset(300);
- break;
-
- case EOT : /*--------------------------------------------*/
- /* EOT */
- /*--------------------------------------------*/
- stat_msg = EOT_msg;
- t1 = timerset (20);
- while (!timeup (t1))
- {
- TIMED_READ(0);
- time_release();
- }
- if (block_number) goto done;
- else goto fubar;
-
- default : /*--------------------------------------------*/
- /* Default */
- /*--------------------------------------------*/
- if (in_char>0)
- begin
- if (!may_be_seadog)
- {
- gotoxy(locate_x,locate_y);
- cprintf("??? [%Xh, blk %d] ",in_char,block_number);
- set_xy(receiving);
- }
- end
-
- /*--------------------------------------------*/
- /* Debris is tolerable for up to the amount */
- /* of time we are willing to wait for a start */
- /* of a block. Right now it is 10 seconds. */
- /*--------------------------------------------*/
- /* if ( (!timeup(block_timer)) and (CARRIER) )
- goto loop_top;
- else
- */
-
- /* If may_be_seadog is set, then we know we should
- get an SOH pretty soon */
- if (timeup(t1) || !may_be_seadog)
- SendNAK();
- break;
-
- end /* switch */
-
- if (errs>14)
- begin
- stat_msg = FUBAR_msg;
- goto fubar;
- end
-
- else if (got_error(WRITE_msg,fname))
- begin
- stat_msg = IO_msg;
- goto fubar;
- end
-
- if (stat_msg)
- begin
- cputs( stat_msg );
- cputs( local_CEOL );
- stat_msg = NULL;
- end
-
- end
- while(CARRIER);
-
- stat_msg = CARRIER_msg;
-
-
- fubar:
-
- if (buffer) free(buffer);
- if (infile)
- begin
- fclose(infile);
- got_error(CLOSE_msg,tmpname);
- unlink(tmpname);
- got_error(UNLINK_msg,tmpname);
- end
-
- CLEAR_OUTBOUND();
-
- if (stat_msg != EOT_msg)
- begin
- for(in_char=0; in_char<5; in_char++)
- SENDBYTE(CAN);
-
- status_line("!File not received: %s",stat_msg);
- end;
-
- CLEAR_INBOUND();
- return NULL;
-
-
- done:
-
- recv_ackless = 0;
- SendACK();
-
- if (buffer) free(buffer);
-
- if (infile)
- begin
- int i, j, k;
- struct FILEINFO dta;
-
- fclose(infile);
- got_error(CLOSE_msg,tmpname);
-
- i = strlen(tmpname) -1;
- j = strlen(final_name) -1;
-
- if (tmpname[i]=='.') tmpname[i]='\0';
- if (final_name[j]=='.')
- {
- final_name[j]='\0';
- --j;
- }
-
- i = 0;
- k = is_arcmail (final_name, j);
- if ((!overwrite) || k)
- {
- while(rename(tmpname,final_name))
- begin
- if (isdigit(final_name[j])) final_name[j]++;
- else final_name[j]='0';
- if (!isdigit(final_name[j])) return(tmpname);
- i = 1;
- end
- CLEAR_IOERR();
- }
- else
- {
- unlink (final_name);
- rename (tmpname, final_name);
- }
- if (i)
- {
- if (locate_y) gotoxy (0, locate_y-1);
- status_line("+Dupe file renamed: %s",final_name);
- }
-
- if (filesecs != -1)
- {
- tzset();
- times.modtime = filesecs+timezone;
- times.actime = filesecs+timezone;
- utime (final_name, ×);
- }
-
- if (!dfind(&dta,final_name,0))
- begin
- if (!i)
- {
- if (locate_y) gotoxy(0,locate_y-1);
- }
- status_line("+Received-S %s",final_name);
- throughput(1,dta.size);
-
- dta.size /= 1024L;
- #ifndef BINKLEY
- cur_user.upld += 1 + (unsigned int )dta.size;
-
- if (cur_user.dnldl>0)
- cur_user.dnldl-= 1 + (unsigned int )dta.size;
- #endif
- strcpy( final_name, dta.name );
- CLEAR_IOERR();
- return final_name; /* signal what file we got */
- end
-
- end
- CLEAR_IOERR();
- return NULL;
-
- end
-
- /* END OF FILE: recv_sl.c */
-